package com.xuecheng.auth.controller;

import com.xuecheng.api.auth.AuthControllerApi;
import com.xuecheng.auth.service.AuthService;
import com.xuecheng.framework.domain.ucenter.ext.AuthToken;
import com.xuecheng.framework.domain.ucenter.request.LoginRequest;
import com.xuecheng.framework.domain.ucenter.response.AuthCode;
import com.xuecheng.framework.domain.ucenter.response.JwtResult;
import com.xuecheng.framework.domain.ucenter.response.LoginResult;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.utils.CookieUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Administrator
 * @version 1.0
 **/
@RestController
@RequestMapping("/")
public class AuthController implements AuthControllerApi {

    @Value("${auth.clientId}")
    String clientId;
    @Value("${auth.clientSecret}")
    String clientSecret;
    @Value("${auth.cookieDomain}")
    String cookieDomain;
    @Value("${auth.cookieMaxAge}")
    int cookieMaxAge;

    @Autowired
    AuthService authService;

    @Override
    @PostMapping("/userlogin")
    public LoginResult login(LoginRequest loginRequest) {
        if(loginRequest == null || StringUtils.isEmpty(loginRequest.getUsername())){
            ExceptionCast.cast(AuthCode.AUTH_USERNAME_NONE);
        }
        if(loginRequest == null || StringUtils.isEmpty(loginRequest.getPassword())){
            ExceptionCast.cast(AuthCode.AUTH_PASSWORD_NONE);
        }
        //账号
        String username = loginRequest.getUsername();
        //密码
        String password = loginRequest.getPassword();

        //申请令牌
        AuthToken authToken =  authService.login(username,password,clientId,clientSecret);

        //用户身份令牌
        String access_token = authToken.getAccess_token();
        //将令牌存储到cookie
        this.saveCookie(access_token);

        return new LoginResult(CommonCode.SUCCESS,access_token);
    }

    @Override
    @GetMapping("/refresh/token")
    public LoginResult refresh(String refreshToken) {
        if (StringUtils.isEmpty(refreshToken)){
            ExceptionCast.cast(AuthCode.AUTH_REFRESH_TOKEN_FAIL);
        }
        AuthToken refresh = authService.refresh(refreshToken, clientId, clientSecret);
        //用户身份令牌
        String access_token = refresh.getAccess_token();
        //将令牌存储到cookie
        this.saveCookie(access_token);

        return new LoginResult(CommonCode.SUCCESS,access_token);
    }
//    ------------------这里是采用成功处理器构造token 方式  的令牌刷新

//    /**
//     * 注入获取client信息的service 此类由spring 容器管理
//     */
//    @Autowired(required = false)
//    private ClientDetailsService clientDetailsService;
//
//    /**
//     * 注入获取验证token的类
//     */
//    @Autowired(required = false)
//    private AuthorizationServerTokenServices authorizationServerTokenServices;
//
//
//    /**
//     * 异常解析类
//     */
//    private WebResponseExceptionTranslator exceptionTranslator = new DefaultWebResponseExceptionTranslator();
//
//    @RequestMapping("${custom.security.core.token-refresh:/token/refresh}")
//    public Object tokenRefresh(HttpServletRequest request, HttpServletResponse response) throws Exception {
//        String refreshToken = request.getParameter("refresh_token");
//        if (StringUtils.hasNotText(refreshToken)) {
//            return new ResponseResult(false, "没有刷新token");
//        }
//        String header = request.getHeader("Authorization");
//        String clietId = null;
//        if (StringUtils.hasText(header) && header.toLowerCase().startsWith("basic ")) {
//            String[] tokens = Basic64Decoder.extractAndDecodeHeader(header);
//            if (tokens != null || tokens.length == 2) {
//                clietId = tokens[0];
//            }
//        }
//        if (clietId == null) {
//            return new ResponseResult(false, "没有client凭证");
//        }
//        ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clietId);
//        TokenRequest tokenRequest = new TokenRequest(Collections.EMPTY_MAP, clietId, clientDetails.getScope(), "custom");
//        // 刷新获取的token
//        OAuth2AccessToken accessToken;
//        try {
//            accessToken = authorizationServerTokenServices.refreshAccessToken(refreshToken, tokenRequest);
//        } catch (InvalidTokenException e) {
//            ResponseEntity<OAuth2Exception> result = exceptionTranslator.translate(e);
//            String message = result.getBody().getMessage();
//            // 是否是过期token判断
//            if (message.contains( "Invalid refresh token (expired): ")) {
//                return new ResponseResult(ResponseEnum.INVALID_REFRESH_TOKEN);
//            } else {
//                return new ResponseResult(false, "刷新token解析异常");
//            }
//        } catch (Exception e) {
//            return new ResponseResult(false, "刷新token异常");
//        }
//        // 创建一个map(返回到前端)
//        Map<String, Object> tokenMap = new ConcurrentHashMap<>(2);
//        tokenMap.put("access_token", accessToken.getValue());
//        tokenMap.put("refresh_token", accessToken.getRefreshToken().getValue());
//        return new ResponseResult(true, tokenMap);
//    }
    //将令牌存储到cookie
    private void saveCookie(String token){

        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        //HttpServletResponse response,String domain,String path, String name, String value, int maxAge,boolean httpOnly
        CookieUtil.addCookie(response,cookieDomain,"/","uid",token,cookieMaxAge,false);

    }
    //从cookie删除token
    private void clearCookie(String token){

        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        //HttpServletResponse response,String domain,String path, String name, String value, int maxAge,boolean httpOnly
        CookieUtil.addCookie(response,cookieDomain,"/","uid",token,0,false);

    }

    //退出
    @Override
    @PostMapping("/userlogout")
    public ResponseResult logout() {
        //取出cookie中的用户身份令牌
        String uid = getTokenFormCookie();
        //删除redis中的token
        boolean result = authService.delToken(uid);
        //清除cookie
        this.clearCookie(uid);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    @Override
    @GetMapping("/userjwt")
    public JwtResult userjwt() {
        //取出cookie中的用户身份令牌
        String uid = getTokenFormCookie();
        if(uid == null){
            return new JwtResult(CommonCode.FAIL,null);
        }

        //拿身份令牌从redis中查询jwt令牌
        AuthToken userToken = authService.getUserToken(uid);
        if(userToken!=null){
            //将jwt令牌返回给用户
            String jwt_token = userToken.getJwt_token();
            return new JwtResult(CommonCode.SUCCESS,jwt_token);
        }
        return null;
    }

    //取出cookie中的身份令牌
    private String getTokenFormCookie(){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Map<String, String> map = CookieUtil.readCookie(request, "uid");
        if(map!=null && map.get("uid")!=null){
            String uid = map.get("uid");
            return uid;
        }
        return null;
    }
}
